#include "HandlerV2.h"

#include <zlib.h>

void testZlib()
{
    /* 原始数据 */
    unsigned char strSrc[] = "hello world! aaaaa bbbbb ccccc ddddd 中文测试 yes";
    unsigned char buf[1024] = {0};
    unsigned char strDst[1024] = {0};
    unsigned long srcLen = sizeof(strSrc);
    unsigned long bufLen = sizeof(buf);
    unsigned long dstLen = sizeof(strDst);

    printf("Src string:%s\nLength:%ld\n", strSrc, srcLen);

    /* 压缩 */
    compress(buf, &bufLen, strSrc, srcLen);
    printf("After Compressed Length:%ld\n", bufLen);

    /* 解压缩 */
    uncompress(strDst, &dstLen, buf, bufLen);
    printf("After UnCompressed Length:%ld\n",dstLen);

    printf("UnCompressed String:%s\n",strDst);
}

HandlerV2::HandlerV2(QObject *parent)
    : Handler(parent)
{
}

void HandlerV2::GetSpriteListFromDataStream(Album &album, QDataStream *streamPtr)
{
    long long realIndexLength = 0;
    for (int i = 0; i < album.Count; i++) {
        SpriteStruct sprite;
        sprite.Index = i;
        sprite.Type = SpriteTypeEnum(ReadInt(streamPtr));
        realIndexLength += 4;
        if (sprite.Type == SpriteTypeEnum::Link) {
            sprite.LinkIndex = ReadInt(streamPtr);
            realIndexLength += 4;
            album.SpriteList.append(sprite);
            continue;
        }
        sprite.CompressMode = CompressModeEnum(ReadInt(streamPtr));
        realIndexLength += 4;
        sprite.Width = ReadInt(streamPtr);
        realIndexLength += 4;
        sprite.Height = ReadInt(streamPtr);
        realIndexLength += 4;
        sprite.Length = ReadInt(streamPtr);
        realIndexLength += 4;
        sprite.X = ReadInt(streamPtr);
        realIndexLength += 4;
        sprite.Y = ReadInt(streamPtr);
        realIndexLength += 4;
        sprite.FrameWidth = ReadInt(streamPtr);
        realIndexLength += 4;
        sprite.FrameHeight = ReadInt(streamPtr);
        realIndexLength += 4;

        album.SpriteList.append(sprite);
    }
    if (realIndexLength < album.IndexLength) {
        qCritical() << Q_FUNC_INFO << "Album data is error!";
        album.SpriteList.clear();
        return;
    }

    ReadAllFromDataStream(streamPtr, album.SpritesDataBa);
    long long dataOffset = 0;
    for (SpriteStruct &sprite : album.SpriteList) {
        if (sprite.Type == SpriteTypeEnum::Link) {
            if (sprite.LinkIndex >= album.SpriteList.size() &&
                sprite.LinkIndex == sprite.Index) {
                qCritical() << Q_FUNC_INFO << "sprite data is error!";
                album.SpriteList.clear();
                return;
            }

            const SpriteStruct &linkSprite = album.SpriteList.at(sprite.LinkIndex);
            sprite.Width = linkSprite.Width;
            sprite.Height = linkSprite.Height;
            sprite.X = linkSprite.X;
            sprite.Y = linkSprite.Y;
            sprite.FrameWidth = linkSprite.FrameWidth;
            sprite.FrameHeight = linkSprite.FrameHeight;
            continue;
        }

        if (sprite.CompressMode == CompressModeEnum::None) {
            sprite.Length = sprite.Width * sprite.Height *
                            (sprite.Type == SpriteTypeEnum::Argb8888 ? 4 : 2);
        }
        sprite.DataOffset = dataOffset;
        dataOffset += sprite.Length;
    }
}

QImage HandlerV2::GetSpriteImg(const Album &album, const SpriteStruct &sprite)
{
    QImage img;
    if (sprite.Type == SpriteTypeEnum::Link) {
        return HandlerV2::GetSpriteImg(album, album.SpriteList[sprite.LinkIndex]);
    }

    const QByteArray &ba = album.SpritesDataBa.mid(sprite.DataOffset, sprite.Length);
    uchar *imgData = (uchar *)(ba.data());
    int imgDataLength = sprite.Length;
    if (sprite.CompressMode == CompressModeEnum::Zlib) {
        const int size = sprite.Width * sprite.Height *
                         (sprite.Type == SpriteTypeEnum::Argb8888 ? 4 : 2);
        unsigned char uncompressBuffer[size];
        uLong uncompressBufferLen = size;
        uchar *compressBuffer = imgData;
        uLong compressBufferLen = imgDataLength;
        int err = uncompress(uncompressBuffer, &uncompressBufferLen, compressBuffer, compressBufferLen);
        if (err != Z_OK) {
            qCritical() << Q_FUNC_INFO << "data uncompress failed, err code:" << err;
            return img;
        }

        GetImgFromUCharArray(img, sprite.Width, sprite.Height,
                            uncompressBuffer, uncompressBufferLen, sprite.Type);
    } else {
        GetImgFromUCharArray(img, sprite.Width, sprite.Height,
                            imgData, imgDataLength, sprite.Type);
    }

    return img;
}
